<?php

namespace App\B2BProject\Custom\Business;

use App\B2BProject\Custom\Member;
use App\B2BProject\Exception\UserTypeException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class Goods extends Model
{
    protected $guarded = ['created_at', 'updated_at', 'store_id', 'class_id', 'category_id'];

    /**
     * 商品所属的分类
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function category()
    {
        return $this->belongsTo('App\B2BProject\Custom\Business\GoodsCategory', 'category_id', 'id');
    }

    /**
     * 获取商品所属的大分类（全局分类）
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function classCategory()
    {
        return $this->belongsTo('App\B2BProject\Custom\Business\GoodsCategory', 'class_id', 'id');
    }

    /**
     * 获取商品店铺
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function store()
    {
        return $this->belongsTo('App\B2BProject\Custom\Business\Store', 'store_id', 'id');
    }

    /**
     * 获取规格
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function goodsSpecification()
    {
        return $this->hasMany('App\B2BProject\Custom\Business\GoodsSpecification', 'goods_id', 'id');
    }

    /**
     * 检查商品是否包含规格数据
     *
     * @return bool
     */
    public function hasSpecification()
    {
        return $this->goodsSpecification()->count() > 0 ?: false;
    }

    /**
     * 商品图片
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function goodsImage()
    {
        return $this->hasMany('App\B2BProject\Custom\Business\GoodsImage', 'goods_id', 'id');
    }

    /**
     * @param Builder $query
     *
     * @return $this
     *
     * @throw UserTypeException
     */
    public function scopeAvailableStore(Builder $query)
    {
        if (\Auth::user()->isPurchaser()) {
            throw new UserTypeException;
        }

        return $query->where('store_id', \Auth::user()->store->id);
    }

    /**
     * 获取可被销售的商品
     *
     * @param Builder $query
     *
     * @return $this
     */
    public function scopeAvailable(Builder $query)
    {
        return $query->where('sell_status', true)->where('strict_lock', false);
    }

    /**
     * 获取可被显示的商品
     *
     * @param Builder   $builder
     * @param bool|true $display
     *
     * @return mixed
     */
    public function scopeDisplay(Builder $builder, $display = true)
    {
        return $builder->available()->where('display', $display);
    }

    /**
     * 获取带有图片的商品
     *
     * @param Builder $builder
     *
     * @return Builder|static
     */
    public function scopeHasCover(Builder $builder)
    {
        return $builder->has('goodsImage');
    }

    /**
     * 获取商品封面
     *
     * @return mixed
     */
    public function cover()
    {
        try {
            return $this->goodsImage()->firstOrFail()->image;
        } catch (\Exception $e) {
            return '';
        }
    }

    /**
     * 获取商品品牌
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function brand()
    {
        return $this->belongsTo('App\B2BProject\Custom\Business\Brand', 'brand_id', 'id');
    }

    /**
     * 获取授权信息列表
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function licensed()
    {
        return $this->hasMany('App\B2BProject\Custom\Business\LicensedGood', 'goods_id', 'id');
    }

    /**
     * 获取是否为供采分销商品
     *
     * @return bool
     */
    public function isDistributorGoods()
    {
        return $this->grant_status ? true : false;
    }

    /**
     * 获取是否为自由集散商品
     *
     * @return bool
     */
    public function isFreeDistributorGoods()
    {
        return !$this->isDistributorGoods();
    }

    /**
     * 判断当前用户是否是该商品的授权用户
     */
    public function isGranted()
    {
        return $this->userIsGranted(\Auth::id());
    }

    /**
     * 查看指定用户是否具有权限
     *
     * @param $user
     *
     * @return bool
     */
    public function userIsGranted($user)
    {
        // 先判断是否为供采分销商品
        if ($this->isFreeDistributorGoods()) {
            return true;
        }

        $authorizations = $this->getAuthorization($user);

        return !is_null($authorizations) ?: false;

    }

    /**
     * 获取分类
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function children()
    {
        return $this->hasMany('App\B2BProject\Custom\Business\Goods', 'parent_id', 'id');
    }


    /**
     * 获取当前商品授权信息表
     *
     * @param $user
     *
     * @return mixed
     */
    public function getAuthorization($user)
    {
        $provider = $this->store->member;

        $goodId = $this->id;

        // 通过关系查询的方式，获取商品是否在有效的授权申请中的商品授权表。
        // 这里面存在四张表之间的查询，分别为：供应商表（member 表） - 授权申请表 - 商品授权表 - 商品表
        // 上述四张表中，由于直接通过商品表反向查询至供应商，涉及的链路复杂，查询效率低，
        // 先通过当前商品获取其供应商，而后顺向寻找其授权表对应的商品授权列表，若当前商品 ID 存在于商品授权列表且有效，则表明授权生效。
        $authorization = $provider->authorizationRequests()->whereHas('licensedGoods', function ($query) use ($goodId) {
            $query->where('status', true)->where('goods_id', $goodId);
        })->available($user)->first();

        return $authorization;
    }

    /**
     * 获取当前商品价格策略
     *
     * @param $user
     *
     * @return bool|int
     */
    public function getPriceStrategy($user = null)
    {
        if (is_null($user)) {
            $user = \Auth::id();
        }

        $authorization = $this->getAuthorization($user);

        if (is_null($authorization)) {
            if ($this->isFreeDistributorGoods()) {
                return 1;
            }

            return false;
        }

        $licensed = $authorization->licensedGoods()->where('goods_id', $this->id)->first();

        return $licensed->priceStrategy->price_strategies;
    }

    /**
     * 获取商品的实际价格
     *
     * @return float
     */
    public function getActualPrice()
    {
        return $this->original_price * $this->getPriceStrategy();
    }

    /**
     * 计算库存
     *
     * @param int      $effect 用于计算的数值，将会作为减数用于库存的计算，若减少库存，则该值应当为负整数，增加库存为正整数
     * @param int|null $specId
     */
    public function stockCompute($effect, $specId = null)
    {
        if ($this->hasSpecification()) {
            if (is_null($specId)) {
                throw new \InvalidArgumentException('该商品必须提供规格参数', 1);
            }

            $spec = $this->goodsSpecification()->whereId($specId)->firstOrFail();

            if (($result = $spec->stock + $effect) < 0) {
                throw new \InvalidArgumentException('该商品库存不足', 2);
            }

            $spec->stock = $result;
            $spec->save();
        } else {
            if (($result = $this->stock + $effect) < 0) {
                throw new \InvalidArgumentException('该商品库存不足', 2);
            }

            $this->stock = $result;
            $this->save();
        }
    }

    /**
     * 获取当前商品下的咨询
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function issues()
    {
        return $this->hasMany('App\B2BProject\Custom\Business\Issue', 'goods_id', 'id');
    }

    /**
     * 获取其所处于购物车的对象集合
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function carts()
    {
        return $this->hasMany('App\B2BProject\Custom\Purchaser\ShoppingCart', 'goods_id', 'id');
    }

    /**
     * @return bool|null
     * @throws \Exception
     */
    public function delete()
    {
        $this->licensed()->delete();
        $this->carts()->delete();

        return parent::delete();
    }

    /**
     * 获取商品的统计对象
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function sellStatistics()
    {
        return $this->hasMany('App\B2BProject\Custom\GoodsSellStatistics', 'goods_id', 'id');
    }
}
